#include "Channel.h"
#include "EventLoop.h"
#include "log.h"

#include <sys/epoll.h>
const int Channel::KnoneEvent_ = 0;
const int Channel::KReadEvent_ = EPOLLIN | EPOLLPRI;
const int Channel::KWriteEvent_ = EPOLLOUT;
Channel::Channel(EventLoop *loop, int fd) : loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false)
{
}
// 事件处理函数
void Channel::handlerEvevt(TimeStamp recvTime)
{
    if (tied_)
    {
        std::shared_ptr<void> guard = tie_.lock();
        if (guard)
        {
            handlerEventWithGuard(recvTime);
        }
    }
    else
    {
        handlerEventWithGuard(recvTime);
    }
}
void Channel::handlerEventWithGuard(TimeStamp receiveTime)
{
    LOG_INFO("Channel handlerEvent :%d\n", revents_);
    if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN))
    {
        if (closeCallBack_)
        {
            closeCallBack_();
        }
    }
    if (revents_ & EPOLLERR)
    {
        if (errorCallBack_)
        {
            closeCallBack_();
        }
    }
    if (revents_ & (EPOLLIN | EPOLLPRI))
    {
        if (readCallBack_)
        {
            readCallBack_(receiveTime);
        }
    }
    if (revents_ & EPOLLOUT)
    {
        if (writeCallBack_)
        {
            writeCallBack_();
        }
    }
}

void Channel::ReadCallBack(ReadEventCallBack cb) { readCallBack_ = std::move(cb); }
void Channel::writeCallBack(EventCallBack cb) { writeCallBack_ = std::move(cb); }
void Channel::errorCallBack(EventCallBack cb) { errorCallBack_ = std::move(cb); }
void Channel::closeCallBack(EventCallBack cb) { closeCallBack_ = std::move(cb); }

//这里有一个强引用,不会轻易被释放,当一个TcpConnection被创建的时候需要调用tie    
void Channel::tie(const std::shared_ptr<void> &obj)
{
    tie_ = obj;
    tied_ = true;
}
// 当channel改变fd中的event后，更新epoll里相应的事件

int Channel::fd() const
{
    return fd_;
}
int Channel::events() const
{
    return events_;
}


bool Channel::isNoneEvent() const
{
    return events_ == KnoneEvent_;
}

// 设置fd对应状态
void Channel::enableReading()
{
    events_ |= KReadEvent_;
    update();
}
void Channel::disableReading()
{
    events_ &= ~KReadEvent_;
    update();
}
void Channel::enableWriting()
{
    events_ |= KWriteEvent_;
    update();
}
void Channel::disableWriting()
{
    events_ &= ~KWriteEvent_;
    update();
}

void Channel::disableAll() { events_ = KnoneEvent_; }

bool Channel::isWriting() const
{
    return events_ & KWriteEvent_;
}
bool Channel::isReading() const
{
    return events_ & KReadEvent_;
}

void Channel::setindex(int idx) { index_ = idx; }
int Channel::index()
{
    return index_;
}
// 在Channel所属的EventLoop中，删除当前的Channel
void Channel::remove()
{
    loop_->removeChannel(this);
}
Channel::~Channel() {};

void Channel::update()
{
    // 通过channel所属的EventLoop向epoll中注册fd对应的事件
    loop_->updateChannel(this);
}
